package rsschart.charter;

import java.util.List;

import rsschart.feed.Category;
import rsschart.feed.DataSet;
import rsschart.feed.DataSets;
import rsschart.feed.RssChart;

public class BarChart extends LineBarCharter implements Charter  {
	
	/**
	 * This charter will work w/ a view area that is 320 units wide and 240 units high
	 * 
	 */
	final int TITLE_Y = 15;
	final int CATG_LABEL_Y = 210;
	final int CATG_TITLE_Y = 220;
	final int Y_AXIS_LABEL_X = 10;
	final int Y_AXIS_LABEL_Y = 110;
	final int Y_AXIS_SIZE = 180;
	final int CHART_TOP = 20;
	final int CHART_X_START = 50;
	final static String BAR_COLOR = "#820f0c";
	final static String BAR_COLOR_END = "#d76461";
	
	
	public String draw(RssChart chart) {
		
		StringBuffer chartSvg = new StringBuffer();
				
		int chartWidth;
		int textCenter;
		boolean legend=false;

		//-- 40 pixels is the "zero" point for the x-axis of the chart
		double currentBarX=CHART_X_START;
		int setCount=1;
		double minVal;
		double maxVal;
		double maxValTick;
		double minValTick;
		
		int maxLog;
		int minLog;
		//-- horizontal space for each bar set
		double catgWidth;
		double yScaleFactor;
		double zeroY;
		
		//-- set the bar area of the chart
		if(legend) {
			chartWidth = 200;
			textCenter = 140;
		}
		else {
			chartWidth = 250;
			textCenter = 175;
		}
		//-- chart object has to be initialized and valid for this call to work
		setCount = chart.getSeriesPointCount();
		catgWidth = chartWidth/setCount;

		//-- draw header svg
		chartSvg.append(CharterUtil.getHeader(chart.getWidth(), chart.getHeight()));
		chartSvg.append("<!-- end header info -->\n");
		
		chartSvg.append("\n<!-- gradient defs -->\n");
		chartSvg.append(drawGradients());
		
		//-- add javascript method for clicking:
		chartSvg.append("\n<!-- onclick method -->\n");
		chartSvg.append(CharterUtil.getClickMethod());
		chartSvg.append(CharterUtil.goToSite());

		//-- draw click instruction:
		chartSvg.append("\n<!-- click instruction -->\n");
		chartSvg.append(CharterUtil.clickNote());
		
		//-- draw the title
		chartSvg.append("\n<!-- title -->\n");
		chartSvg.append(CharterUtil.getTitle(textCenter, TITLE_Y, chart.getTitle()));

		//-- draw backframe
		chartSvg.append("\n<!-- chart background -->\n");
		chartSvg.append(CharterUtil.getChartFrame(CHART_X_START, CHART_TOP, chartWidth, Y_AXIS_SIZE));
		
		//-- find the y-axis bounds
		minVal = getMinValue(chart.getDataSets(), chart.getSeriesPointCount(), false);
		minVal = minVal > 0 ? 0 : minVal;
		maxVal = getMaxValue(chart.getDataSets(), chart.getSeriesPointCount(), false);
		
		//--
		maxLog = (int)Math.log10(maxVal);
		minLog=0;
		if (minVal!=0) {		
			minLog = (int)Math.log10(Math.abs(minVal));
		}
		
		//-- this section sets the maximum and minimum y bounds of the chart based on the size of the max/min val numbers
		double maxFull, maxHalf;
		double minFull, minHalf;
		
		maxFull = (int)(maxVal / Math.pow(10, maxLog)) * Math.pow(10, maxLog) 
			+ Math.pow(10, maxLog);
		maxHalf = (int)(maxVal / Math.pow(10, maxLog)) * Math.pow(10, maxLog) 
			+ Math.pow(10, maxLog)/2;
		if (maxVal>maxHalf) {
			maxValTick = maxFull;
		}
		else {
			maxValTick = maxHalf;
		}
		
		minValTick = 0;
		if (minVal!=0) {
			minFull = -1.0 * (int)(Math.abs(minVal) / Math.pow(10, minLog)) 
				* Math.pow(10, minLog) + Math.pow(10, minLog);
			minHalf = -1.0 * (int)(Math.abs(minVal) / Math.pow(10, minLog)) 
				* Math.pow(10, minLog) + Math.pow(10, minLog)/2;
			if (Math.abs(minVal)>Math.abs(minHalf)) {
				minValTick = minFull;
			}
			else {
				minValTick = minHalf;
			}
		}

		yScaleFactor = (maxValTick - minValTick)/ Y_AXIS_SIZE;
		
		//-- where is the Y=zero point? (:
		zeroY = maxValTick/(maxValTick-minValTick) * Y_AXIS_SIZE + CHART_TOP;
		
		//-- draw bars and labels for each category:
		//-- the standard bar chart works on one data series:
		DataSets dataSets;
		Category category;
		dataSets = chart.getDataSets();
		category = chart.getCategory();
		//-- should trap for exceptions here...
		DataSet dataSet = (DataSet)dataSets.iterator().next();
		String[] values = dataSet.getValue();
		
		String[] catgLabels = category.getValue(); 
		double value=0.0;
		
		chartSvg.append("<!-- draw bars-->\n");
		
		StringBuffer barContent = new StringBuffer();
		StringBuffer catgLabelContent = new StringBuffer();
		//-- to do: explain difference between dataSetsName and dataSetName
		String dataSetsName = chart.getDataSetsName();
		String dataSetsValueLabel = chart.getDataSetsValueLabel();
		String dataSetName = dataSet.getName();
		String catgName = category.getName();
		//-- probably should not be hard-coded... :
		String link = "./clickChart";

		for (int i=0; i<setCount;i++) {
			if (values.length>=i) {
				value = Double.parseDouble(values[i]);
				barContent.append(drawBar(currentBarX, catgWidth, value, yScaleFactor, zeroY, 
						                  link, catgName, catgLabels[i], dataSetsName, dataSetName));
			}
			catgLabelContent.append(drawCatgLabel(currentBarX+(catgWidth/2), CATG_LABEL_Y, catgLabels[i]));
			currentBarX += catgWidth;
		}
		
		chartSvg.append(barContent.toString());
		chartSvg.append("<!-- category lables -->\n");
		chartSvg.append(catgLabelContent.toString());
		
		//-- draw y-axis ticks:
		double tickIncVal;
		double currentTickVal;
		double yTick;
		double tickBase;
		tickIncVal = getTickIncVal(maxValTick, minValTick);
		currentTickVal=tickIncVal;
		//-- draw above zero ticks:
		chartSvg.append("<!-- tick marks -->\n");
		if (maxVal > 0) {
			tickBase = zeroY;
			while(currentTickVal<=maxValTick) {
				yTick = tickBase - (tickIncVal/yScaleFactor);
				chartSvg.append(drawTickMark(currentTickVal, yTick));
				tickBase =yTick;
				currentTickVal += tickIncVal;
			}
		}
		//-- draw below zero ticks:
		

		//-- draw category title
		chartSvg.append(drawCatgLabel(textCenter, CATG_TITLE_Y, catgName));
		
		//-- draw y-axis label:
		chartSvg.append(drawYAxisLabel(Y_AXIS_LABEL_X, Y_AXIS_LABEL_Y, dataSetsValueLabel));

		chartSvg.append(CharterUtil.getClose());
		return chartSvg.toString();
	}
	
	private String drawBar(double startX, 
							double width, 
							double value, 
							double scaleFactor, 
							double zeroY,
							String linkUrl,
							String catg,
							String catgVal,
							String dataSet,
							String dataSetVal) {
//		  <rect x="60" y="130" width="30" height="20"
//		        fill="#D16447" stroke="none"  stroke-width="0"/>
		String bar;
		String onclick;
		double x;
		double y;
		double w;
		double h;
		
		if (value>0) {
			h = value/scaleFactor;
			y = zeroY - h;
		}
		else {
			h = value/scaleFactor;
			y = zeroY;
		}
		x = startX + 0.3*width;
		w = 0.4 * width;
		
		onclick = CharterUtil.getDoLink("doLink", linkUrl, catg, catgVal, dataSet, dataSetVal, Double.toString(value));

		/*
		bar = "<rect x=\""+ x + "\" y=\""+ y + "\" width=\"" + w + "\" height=\"" + h + 
			"\" style=\"fill:url(#standard-grad)\" stroke=\"none\"  stroke-width=\"0\"" +
					" cursor=\"pointer\"" +
					" onclick='" + onclick + "'/>\n";
		*/
		
		TagUtil barTag = new TagUtil("rect");
		barTag.addAttrib("x", String.valueOf(x));
		barTag.addAttrib("y", String.valueOf(y));
		barTag.addAttrib("width", String.valueOf(w));
		barTag.addAttrib("height", String.valueOf(h));
		barTag.addAttrib("style", "fill:url(#standard-grad)");
		barTag.addAttrib("stroke", "none");
		barTag.addAttrib("stroke-width", "0");
		barTag.addAttrib("cursor", "pointer");
		barTag.addAttrib("onclick", onclick);

		bar = barTag.write(true);
		
		return bar;
	}

	// to do: use the common method in place...
	private static String drawGradients() {
		StringBuffer gradient = new StringBuffer();
		
		gradient.append("<defs>\n");
		gradient.append("<linearGradient id=\"standard-grad\" x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"0%\">\n");
		gradient.append("<stop offset=\"0%\" style=\"stop-color:" + BAR_COLOR + ";stop-opacity:1\"/>\n");
		gradient.append("<stop offset=\"65%\" style=\"stop-color:" + BAR_COLOR_END + ";stop-opacity:1\"/>\n");
		gradient.append("<stop offset=\"100%\" style=\"stop-color:" + BAR_COLOR + ";stop-opacity:1\"/>\n");
		gradient.append("</linearGradient>\n");
		gradient.append("<linearGradient id=\"background-grad\" x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"0%\">\n");
		gradient.append("<stop offset=\"0%\" style=\"stop-color:#dedede;stop-opacity:1\"/>\n");
		gradient.append("<stop offset=\"100%\" style=\"stop-color:#ffffff;stop-opacity:1\"/>\n");
		gradient.append("</linearGradient>\n");
		gradient.append("</defs>\n");

		
		return gradient.toString();
		
	}
	
	
}
